PACKUSWBmnemonic把两组有符号 16 位整数压缩成无符号 8 位整数,并将越界值钳制到 0…255。
PACKUSWB(Pack with Unsigned Saturation)把两个操作数中的有符号 word(int16)转换成无符号 byte(uint8),再打包进目标寄存器。转换采用饱和规则,不会简单截断高位。
PACKUSWB 02xmm0, 03xmm1/m128PACKUSWBmnemonic把两组有符号 16 位整数压缩成无符号 8 位整数,并将越界值钳制到 0…255。
xmm0destination原有的 8 个 int16 转换后进入结果的低 8 个 byte,随后被结果覆盖。
xmm1/m128source另外 8 个 int16 转换后进入结果的高 8 个 byte。
对每个有符号 16 位输入 x,输出为:
0, x < 0
sat_u8 = x, 0 <= x <= 255
255, x > 255输入 int16 | 输出 uint8 | 原因 |
|---|---|---|
| -20 | 0 | 低于无符号 byte 下界 |
| 0 | 0 | 范围内 |
| 127 | 127 | 范围内 |
| 255 | 255 | 范围内 |
| 256 | 255 | 高于无符号 byte 上界 |
| 1000 | 255 | 高于无符号 byte 上界 |
这与普通窄化转换不同。例如,截断 256 的低 8 位会得到 0,而 PACKUSWB 得到 255。
每个 XMM 源包含 8 个 word,结果 XMM 包含 16 个 byte。以下数组都按低位元素到高位元素书写:
[127:0][127:0][127:0]输入元素各占 16 bits,饱和后各占 8 bits;每个圆球表示一个完整元素。结果低 8 bytes 来自 xmm0,高 8 bytes 来自 xmm1。
[127:0][127:0][127:0]xmm0 words = [-20, 0, 1, 127, 255, 256, 1000, 42]
xmm1 words = [300, 254, -1, 128, 10, 500, 255, 256]
pack xmm0 = [ 0, 0, 1, 127, 255, 255, 255, 42]
pack xmm1 = [255, 254, 0, 128, 10, 255, 255, 255]
result = [ 0, 0, 1, 127, 255, 255, 255, 42, 255, 254, 0, 128, 10, 255, 255, 255]也就是说,第一源的转换结果进入目标低半部,第二源的转换结果进入目标高半部:
DEST.byte[0..7] = sat_u8(OLD_DEST.word[0..7])
DEST.byte[8..15] = sat_u8(SRC.word[0..7])| 指令 | 输入与输出 | 指令集 | 特点 |
|---|---|---|---|
PACKUSWB mm, mm/m64 | 8 × int16 → 8 × uint8 | MMX | 使用 MMX 寄存器 |
PACKUSWB xmm1, xmm2/m128 | 16 × int16 → 16 × uint8 | SSE2 | 两操作数,覆盖目标 |
VPACKUSWB xmm1, xmm2, xmm3/m128 | 16 × int16 → 16 × uint8 | AVX | 三操作数 |
VPACKUSWB ymm1, ymm2, ymm3/m256 | 32 × int16 → 32 × uint8 | AVX2 | 每个 128 位 lane 独立打包 |
VPACKUSWB zmm1 {k1}{z}, zmm2, zmm3/m512 | 64 × int16 → 64 × uint8 | AVX-512BW | 支持 byte 粒度写掩码 |
PACKUSWB 不修改 EFLAGS,也不产生 SIMD 浮点异常。
